//开始
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TWEEN } from "three/examples/jsm/libs/tween.module.min";
import { CSS3DRenderer } from "three/examples/jsm/renderers/css3drenderer";
import { loaderModel } from "./threeLoadModel.js";
import useCounterStore from "../../stores/counter.js";
import $ from "jquery";
import { texture } from "three/examples/jsm/nodes/Nodes.js";
let element = undefined;
let width = undefined;
let height = undefined;
export let scene = undefined;
let camera = undefined;
let renderer = undefined;
let controls = undefined;
let mouse = {};
let mouseClick = {};
let mouseClickTime = undefined;
let raycaster = undefined;
let curObj = undefined;
//灯光
let ambientLight = undefined;
let directLight = undefined;
let textureCube = undefined;
let label3DRender = undefined;
let css3dLable = undefined;
export let css3dLabelGroup = undefined;
let labelGroup = undefined;
let css3dLabelXQGroup = undefined;
let modelLcGroup = undefined;
let gridGroup = undefined;
export let batteryGroup = undefined;
let store = undefined;
let flag = true;
export function initThree(id) {
  //创建从vue页面加载three的入口
  THREE.Cache.enabled = true;
  element = document.getElementById(id);
  width = element.clientWidth;
  height = element.clientHeight;
  createGroup();
  //创建场景
  createScene();
  //创建摄像机
  createCamera();
  //创建灯光,白色环境光，光照强度为1
  createLight();
  //创建渲染器
  createRenderer();
  createControls();
  skyCube();
  css3DRenderer(width, height, element);
  pointGeometry();
  loaderModel(scene);
  window.closeLabel = closeLabel;
  store = useCounterStore();
}

function createGroup() {
  css3dLabelGroup = new THREE.Group();
  css3dLabelGroup.name = "css3dLabelGroup";
  labelGroup = new THREE.Group();
  labelGroup.name = "labelGroup";
  css3dLabelXQGroup = new THREE.Group();
  css3dLabelXQGroup.name = "css3dLabelXQGroup";
  modelLcGroup = new THREE.Group();
  modelLcGroup.name = "modelLcGroup";
  gridGroup = new THREE.Group();
  gridGroup.name = "gridGroup";
  batteryGroup = new THREE.Group();
  batteryGroup.name = "batteryGroup";
}

function createScene() {
  scene = new THREE.Scene();
  //scene.background = new THREE.Color(0,0,0);
  scene.add(css3dLabelGroup);
  scene.add(labelGroup);
  scene.add(css3dLabelXQGroup);
  scene.add(modelLcGroup);
  scene.add(gridGroup);
  scene.add(batteryGroup);
}
function createCamera() {
  camera = new THREE.PerspectiveCamera(45, width / height, 1, 80000000);
  camera.position.z = 100;
}

function createLight() {
  ambientLight = new THREE.AmbientLight(0xffffff, 1);
  scene.add(ambientLight);

  directLight = new THREE.DirectionalLight(0xffffff, 1);
  scene.add(directLight);
}
function createRenderer() {
  renderer = new THREE.WebGLRenderer({
    precision: "highp",
    alpha: true,
    antialias: true,
  });
  renderer.shadowMap.enabled = true;
  renderer.autoClear = true;
  renderer.outputEncoding = THREE.sRGBEncoding; //調整色彩飽和度
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);
  element.appendChild(renderer.domElement);
  element.addEventListener("pointermove", mouseMove, false);
  element.addEventListener("click", mouseUp, false);
  element.addEventListener("pointerdown", mouseDown, false);
}
function mouseMove() {
  mouse.x =
    ((window.event.clientX - element.getBoundingClientRect().left) /
      element.offsetWidth) *
      2 -
    1;
  mouse.y =
    -(
      (window.event.clientY - element.getBoundingClientRect().top) /
      element.offsetHeight
    ) *
      2 +
    1;
  document.body.style.cursor = "default";
  raycaster = new THREE.Raycaster();
  raycaster.setFromCamera(mouse, camera);
}
function mouseUp() {
  if (window.event.button == 0) {
    if (
      window.event.clientX - mouseClick.x <= 10 &&
      window.event.clientY - mouseClick.y <= 10 &&
      Date.now() - mouseClickTime < 150 &&
      flag == true
    ) {
      raycaster = new THREE.Raycaster();
      raycaster.setFromCamera(mouse, camera);
      // let mergedArr = batteryGroup.children.concat(
      //   batteryBGroup.children,
      //   batteryCGroup.children,
      //   batteryDGroup.children
      // );
      let intersects = raycaster.intersectObjects(batteryGroup.children, true);
      if (intersects.length > 0) {
        let curObj = intersects[0].object;
        showLabel(curObj);
      }
    }
  } else if (window.event.button == 2) {
    if (
      window.event.clientX - mouseClick.x <= 5 &&
      window.event.clientY - mouseClick.y <= 5 &&
      Date.now() - mouseClickTime < 150
    ) {
      raycaster = new THREE.Raycaster();
      raycaster.setFromCamera(mouse, camera);
      //initControl();
    }
  }
}
function mouseDown() {
  mouseClick.x = window.event.clientX;
  mouseClick.y = window.event.clientY;
  mouseClickTime = Date.now();
}
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);
  controls.object.position.set(
    -23.542487313761264,
    35.173597343161916,
    -71.62817387795468
  );
  controls.target.set(
    0.2402553764387293,
    14.960956272319349,
    -34.00236615032259
  );
}
//天空盒子
function skyCube() {
  var r = "static/model/skybox/";
  var urls = [
    r + "nx.jpg",
    r + "ny.jpg",
    r + "nz.jpg",
    r + "px.jpg",
    r + "py.jpg",
    r + "pz.jpg",
  ];

  textureCube = new THREE.CubeTextureLoader().load(urls);
  textureCube.format = THREE.RGBFormat;
  textureCube.mapping = THREE.CubeReflectionMapping;
  //scene.background = textureCube;
}
function css3DRenderer(width, height, element) {
  label3DRender = new CSS3DRenderer();
  label3DRender.setSize(width, height);
  label3DRender.domElement.style.position = "absolute";
  label3DRender.domElement.style.top = "0px";
  label3DRender.domElement.style.pointerEvents = "none";
  element.appendChild(label3DRender.domElement);
}

function pointGeometry() {
  let geometry = new THREE.BoxGeometry(5, 5, 5);
  var starsMaterial = new THREE.PointsMaterial({
    color: 0xfffff,
  });
  for (var i = 0; i < 10000; i++) {
    var randomX = -13000 + Math.round(Math.random() * 30000);
    var randomY = -13000 + Math.round(Math.random() * 30000);
    var randomZ = -13000 + Math.round(Math.random() * 30000);
    let mesh = new THREE.Mesh(geometry, starsMaterial);
    mesh.position.x = randomX;
    mesh.position.y = randomY;
    mesh.position.z = randomZ;
    scene.add(mesh);
  }

  //projects.push(mesh)
}
export function closeLabel(label, e) {
  flag = false;
  let curObj = css3dLabelGroup.getObjectByName(label);
  if (curObj) {
    curObj.scale.set(0.05, 0.05, 0.05);
    curObj.visible = false;
    curObj.userData.click = false;
  }
  let modelName = `${label.slice(3)}`;
  let model = batteryGroup.getObjectByName(modelName);
  let bodyModel = batteryGroup.getObjectByName(`body-${label.slice(3)}`);
  $(`.bq-${label.slice(3)}`)
    .removeClass("default")
    .removeClass("red")
    .removeClass("orange")
    .removeClass("purple")
    .removeClass("yellow")
    .removeClass("cyan")
    .addClass("default");
  if (model) {
    bodyModel.children.map((item) => {
      item.material = item.userData.material.clone();
      item.material.color = item.userData.material.color;
    });
    model.scale.set(1, 1, 1);
    setTimeout(() => {
      flag = true;
    }, 300);
  }
}

function showLabel(curObj) {
  let label = curObj.name;
  if (label.indexOf("head") < 0 && label.indexOf("body") < 0) {
    label = curObj.parent.name;
  }
  let bqLabel = `bq-${label.slice(5)}`;
  $(`.${bqLabel}`)
    .removeClass("default")
    .removeClass("red")
    .removeClass("orange")
    .removeClass("purple")
    .removeClass("yellow")
    .removeClass("cyan")
    .addClass("cyan");
  let curLabel = css3dLabelGroup.getObjectByName(bqLabel);
  if (curLabel && curLabel.scale.x == 0.06) {
    curLabel.visible = false;
    curLabel.userData.click = false;
    curLabel.scale.set(0.05, 0.05, 0.05);
    $(`.${bqLabel}`)
      .removeClass("default")
      .removeClass("red")
      .removeClass("orange")
      .removeClass("purple")
      .removeClass("yellow")
      .removeClass("cyan")
      .addClass("default");
  } else if (curLabel) {
    curLabel.visible = true;
    curLabel.userData.click = true;
    curLabel.scale.set(0.06, 0.06, 0.06);
  }
  let modelName = `${label.slice(5)}`;
  let model = batteryGroup.getObjectByName(modelName);
  let bodyModelName = `body-${label.slice(5)}`;
  let bodyModel = batteryGroup.getObjectByName(bodyModelName);
  if (model && model.scale.x == 1.1) {
    bodyModel.children.map((item) => {
      item.material = item.userData.material.clone();
      item.material.color = item.userData.material.color;
    });
    model.scale.set(1, 1, 1);
  } else if (model) {
    bodyModel.children.map((item) => {
      item.material = item.userData.material.clone();
      item.material.color = new THREE.Color(0xbbffee);
    });
    model.scale.set(1.1, 1.1, 1);
  }
}
export function render() {
  TWEEN.update();
  if (controls) {
    controls.update();
  }

  if (label3DRender) {
    label3DRender.render(scene, camera);
  }
  renderer.setSize(width, height);
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

// tween
function initControl() {
  if (curObj) {
    curObj.visible = false;
    curObj = undefined;
  }
  setCamera(
    {
      x: -23.542487313761264,
      y: 35.173597343161916,
      z: -71.62817387795468,
    },
    { x: 0.2402553764387293, y: 14.960956272319349, z: -34.00236615032259 }
  );
}

function moveModel(model) {
  let tween = new TWEEN.Tween(model);
}

function setCamera(position, target) {
  let tween = new TWEEN.Tween({
    px: controls.object.position.x, // 起始相机位置x
    py: controls.object.position.y, // 起始相机位置y
    pz: controls.object.position.z, // 起始相机位置z
    tx: controls.target.x, // 控制点的中心点x 起始目标位置x
    ty: controls.target.y, // 控制点的中心点y 起始目标位置y
    tz: controls.target.z, // 控制点的中心点z 起始目标位置z
  });
  tween.to(
    {
      px: position.x,
      py: position.y,
      pz: position.z,
      tx: target.x,
      ty: target.y,
      tz: target.z,
    },
    1000
  );
  tween.onUpdate(function (pos) {
    controls.object.position.x = pos.px;
    controls.object.position.y = pos.py;
    controls.object.position.z = pos.pz;
    controls.target.x = pos.tx;
    controls.target.y = pos.ty;
    controls.target.z = pos.tz;
  });
  tween.easing(TWEEN.Easing.Cubic.InOut);
  tween.start();
}

/**
 * 修改标签内容
 * @param {传入数据} data
 */
export function updateLabel(data) {
  if (data && data.battery) {
    let mesh = batteryGroup.getObjectByName(`body-${data.battery}`);
    let labelMesh = css3dLabelGroup.getObjectByName(`bq-${data.battery}`);
    if (mesh && mesh.children.length > 0) {
      switch (parseInt(data.state.batteryState)) {
        case 0:
          if (labelMesh.userData.click == false) {
            mesh.children.map((item) => {
              item.material = item.userData.material.clone();
              item.material.color = item.userData.material.color;
            });
            labelMesh.visible = false;
          }
          break;
        case 1:
          mesh.children.map((item) => {
            item.material = item.userData.material.clone();
            item.material.color = new THREE.Color(0xff1010);
          });
          labelMesh.visible = true;
          break;
        case 2:
          mesh.children.map((item) => {
            item.material = item.userData.material.clone();
            item.material.color = new THREE.Color(0xfad60d);
          });
          labelMesh.visible = true;
          break;
        case 3:
          mesh.children.map((item) => {
            item.material = item.userData.material.clone();
            item.material.color = new THREE.Color(0xff690e);
          });
          labelMesh.visible = true;
          break;
        case 4:
          mesh.children.map((item) => {
            item.material = item.userData.material.clone();
            item.material.color = new THREE.Color(0x8650ff);
          });
          labelMesh.visible = true;
          break;
        default:
          break;
      }
    }
    let batteryState = store.batteryStatus[data.state.batteryState];
    let temperatureState = store.temperatureState[data.state.temperatureState];
    let strainState = store.strainState[data.state.strainState];
    if (batteryState) {
      if (parseInt(data.state.batteryState) != 0) {
        $(`.bq-${data.battery}`)
          .removeClass("default")
          .removeClass("red")
          .removeClass("orange")
          .removeClass("purple")
          .removeClass("yellow")
          .removeClass("cyan")
          .addClass(batteryState.className);
      } else {
        if (labelMesh && labelMesh.userData.click == false) {
          $(`.bq-${data.battery}`)
            .removeClass("default")
            .removeClass("red")
            .removeClass("orange")
            .removeClass("purple")
            .removeClass("yellow")
            .removeClass("cyan")
            .addClass(batteryState.className);
        } else if (labelMesh && labelMesh.userData.click == true) {
          $(`.bq-${data.battery}`)
            .removeClass("default")
            .removeClass("red")
            .removeClass("orange")
            .removeClass("purple")
            .removeClass("yellow")
            .removeClass("cyan")
            .addClass("cyan");
        }
      }
    }
    if (temperatureState) {
      $(`.bq-${data.battery} .labelNrwd,.bq-${data.battery} .labelNrZtWd`)
        .removeClass("default")
        .removeClass("red")
        .removeClass("orange")
        .removeClass("purple")
        .removeClass("yellow")
        .removeClass("cyan")
        .addClass(temperatureState.className);
      $(`.bq-${data.battery} .labelNrZtWd`).text(`${temperatureState.text}`);
    }
    if (strainState) {
      $(`.bq-${data.battery} .labelyb,.bq-${data.battery} .labelNrZtYb`)
        .removeClass("default")
        .removeClass("red")
        .removeClass("orange")
        .removeClass("purple")
        .removeClass("yellow")
        .removeClass("cyan")
        .addClass(strainState.className);
      $(`.bq-${data.battery} .labelNrZtYb`).text(`${strainState.text}`);
    }
    $(`.bq-${data.battery} .labelNrwd`).text(`${data.temperature.toFixed(2)}℃`);

    $(`.bq-${data.battery} .labelyb`).text(`${data.deformation.toFixed(2)}με`);
  }
}

export function hideLabel() {
  if (css3dLabelGroup && css3dLabelGroup.children.length > 0) {
    css3dLabelGroup.children.map((item) => {
      if (item.userData.click == false) {
        item.visible = false;
      }
    });
  }
}
